#ifndef __LLIST_V2_H__
#define __LLIST_V2_H__

#include "ListIter.h"

template <class T>
class LList
{
  public:
    virtual ~LList();                   //  DTOR
    LList();                            //  CTOR
    LList(const LList& );               //  copy CTOR
    LList& operator=(const LList& );    //  Assigment operator


class ConstIterator;

class Iterator      //  nested class Iterator
{
 public:
    //  ~Iterator();                                    //  use default
    //  Iterator(const Iterator&)                       //  use default
    //  const Iterator& operator=(const Iterator&)      //  use default

//  friend functions for building from private CTOR Iterator
    friend Iterator LList<T>::Begin();
    friend Iterator LList<T>::End();

    Iterator& operator++();
    Iterator& operator--();
    T*  Get() const;                            //  Get also from const Iterator


 protected:
    ListIter GetListIter()
    {
        return m_iter;
    }
 private:
    //  friend logic operators for comparing iterators
//    friend bool operator==<T>(const ConstIterator&, const ConstIterator&);
//    friend bool operator!=<T>(const ConstIterator&, const ConstIterator&);
    friend Iterator LList<T>::Insert(ConstIterator , T*);
    friend Iterator LList<T>::Remove(ConstIterator);

    ListIter GetListIter() const;

    friend ListIter LList<T>::ConstIterator::GetListIter() const;

    ListIter m_iter;
#ifdef _DEBUG
    List*   m_list;
#endif  //  #ifdef _DEBUG

    Iterator(ListIter
#ifdef _DEBUG           //  in debug mode also another parameter for init the value of poined list
    , List*
#endif  //  #ifdef _DEBUG
                    );      //  private CTOR from ListIter. can only initalize in Begin() or End() methods of LList.
};

class ConstIterator
{
 public:
    //  ~ConstIterator();                                           //  use default
    //  ConstIterator(const ConstIterator&)                         //  use default
    //  const ConstIterator& operator=(const ConstIterator&)        //  use default

    ConstIterator(const Iterator&);        //  CTOR from Iterator for implicit conversion
    ConstIterator& operator++();
    ConstIterator& operator--();
    const T* Get() const;

    private:
        ListIter GetListIter() const;

        Iterator m_citer;
};



    ConstIterator Begin() const;        //  for const list return ConstIterator for not changing data
    ConstIterator End()   const;

    Iterator    Begin();
    Iterator    End();

    Iterator    Insert(ConstIterator , T*);
    Iterator    Remove(ConstIterator);

    bool        IsEmpty() const;    //  relevant also for const List

  private:
    List* m_list;
};


/** Decleration of non member functions    **/
//  Boolean operators, works also on Iterator and ConstIterator comparing, use the conversion from Iterator to ConstIterator
template <class T>
bool operator==(const typename LList<T>::ConstIterator&, const typename LList<T>::ConstIterator&);

template <class T>
bool operator!=(const typename LList<T>::ConstIterator&, const typename LList<T>::ConstIterator&);
/*******************************************/




//---------------------------------------------------------------------------------------



template <class T>
LList<T>::~LList()                           //  DTOR
{
    ListDelete(m_list);
}

template <class T>
LList<T>::LList()                            //  CTOR
{
    m_list = ListNew();
}


//template <class T>
//LList<T>::LList(const LList& _list)               //  copy CTOR
//{
//    m_list = ListNew();
//
//
//
//
//}
//    template <class T>
//    LList<T>& LList<T>::operator=(const LList& _list)    //  Assigment operator
//    {
//
//    }

template <class T>
typename LList<T>::Iterator& LList<T>::Iterator::operator++()
{
    m_iter = ListNext(m_iter);
    return *this;
}

template <class T>
typename LList<T>::Iterator& LList<T>::Iterator::operator--()
{
    m_iter = ListPrev(m_iter);
    return *this;
}

template <class T>
T*  LList<T>::Iterator::Get() const                            //  Get also from const Iterator
{
    return static_cast<T*>(ListGetData(m_iter));
}


template <class T>
typename LList<T>::ConstIterator& LList<T>::ConstIterator::operator++()
{
    ++m_citer;
    return *this;
}

template <class T>
typename LList<T>::ConstIterator& LList<T>::ConstIterator::operator--()
{
    --m_citer;
    return *this;
}

template <class T>
ListIter LList<T>::Iterator::GetListIter() const
{
    return m_iter;
}


template <class T>
ListIter LList<T>::ConstIterator::GetListIter() const
{
    return m_citer.GetListIter();
}

//ConstIterator Begin() const;
 //   ConstIterator End()   const;
template <class T>
typename LList<T>::Iterator  LList<T>::Begin()
{
    return Iterator(ListBegin(m_list));
}

template <class T>
typename LList<T>::Iterator  LList<T>::End()
{
    return Iterator(ListEnd(m_list));
}
//
//template <class T>
//ListIter LList<T>::ConstIterator::GetListIter()
//{
//    return m_iter.m_iter;
//}

template <class T>
typename LList<T>::Iterator  LList<T>::Insert(ConstIterator _cit, T* _item)
{
    return Iterator(ListInsert(_cit.GetListIter() , _item));
}

//template <class T>
//typename LList<T>::Iterator  LList<T>::Remove(ConstIterator _cit)
//{
//    return Iterator(ListRemove(_cit.GetListIter()));
//}



#endif // __LLIST_V2_H__
